// 洗牌与发牌
#include <iostream>
using namespace std;

enum class Suit {
    diamond,
    club,
    heart,
    spade,
};

enum class Rank {
    two = 2,
    three, four, five, six, seven, eight, nine, ten,
    jack, queen, king, ace
};

class Card {
private:
    Rank rank;
    Suit suit;

public:
    Card() {
        suit = Suit::club;
        rank = Rank::two;
    }
    void SetSuit(Suit suit) { this->suit = suit; }
    void SetRank(Rank rank) { this->rank = rank; }
    void ShowCard();
    int operator>(Card rhs) {
        return rank > rhs.rank
            || (rank == rhs.rank && suit > rhs.suit);
    }
};

class Player {
private:
    Card hand[4];
    int handSize;

public:
    Player() {
        cout << "在Player构造函数中\n";
        handSize = 0;
    }

    void GetCard(Card card) {
        hand[handSize++] = card;
    }

    void ShowHand() {
        for (int i = 0; i < handSize; i++) {
            hand[i].ShowCard();
        }
        handSize = 0;
    }
};

class Dealer : public Player {
private:
    Card cards[52];
    int idx[52];
    int top;

public:
    Dealer();
    void Shuffle();
    void ShowOrigCards();
    void ShowShuffledCards();
    void Deal4Cards(Player* player);
    int WhereIsTheTop() { return top; }
};

int ShowMenu();

int main() {
    Dealer bob;
    Player lucy;

    bob.Shuffle();

    bool goodbyte = false;
    while (false == goodbyte) {
        switch (ShowMenu()) {
            case 1:
                bob.ShowOrigCards();
                break;
            case 2:
                bob.ShowShuffledCards();
                break;
            case 3:
                bob.Shuffle();
                bob.ShowShuffledCards();
                break;
            case 4:
                if (bob.WhereIsTheTop() < 43) {
                    // 发牌
                    bob.Deal4Cards(&lucy);

                    cout << "玩家 lucy 手中的牌是:";
                    lucy.ShowHand();
                    cout << "\n";

                    cout << "玩家 bob 手中的牌是:";
                    bob.ShowHand();
                    cout << "\n";
                }
                else {
                    cout << "抱歉，牌不够了\n";
                }
                break;
            case 5:
                goodbyte = true;
                break;
            default:
                cout << "无效选项\n";
                break;
        }
    }

    cout << "玩得开心，再见\n";
}

void Card::ShowCard() {
    switch (suit) {
        case Suit::spade:
            cout << " ♠";
            break;
        case Suit::heart:
            cout << " ♥";
            break;
        case Suit::diamond:
            cout << " ♦";
            break;
        case Suit::club:
            cout << " ♣";
            break;
    }
    if (int(rank) < 11) {
        cout << int(rank);
    }
    else if (rank == Rank::jack) {
        cout << "J";
    }
    else if (rank == Rank::queen) {
        cout << "Q";
    }
    else if (rank == Rank::king) {
        cout << "K";
    }
    else {
        cout << "A";
    }
}

Dealer::Dealer() {
    cout << "在Dealer构造函数中\n";

    top = 0;

    for (int i = 3, c = 0; i >= 0; i--) {
        for (int j = 14; j >= 2; j--, c++) {
            cards[c].SetSuit(Suit(i));
            cards[c].SetRank(Rank(j));
        }
    }

    for (int i = 0; i < 52; i++) {
        idx[i] = i;
    }
}

void Dealer::Shuffle() {
    for (int i = 52; i >= 1; i--) {
        int r = rand() % i; // [0, i)

        // 让最后一个位置(i-1)为剩余的全部牌中的随机一个
        int c = idx[i-1];
        idx[i - 1] = idx[r];
        idx[r] = c;
    }
}

void Dealer::ShowOrigCards() {
    for (int i = 0; i < 52; i++) {
        cards[i].ShowCard();

        // 一组最后一张
        if (i % 13 == 12) {
            cout << "\n";
        }
    }
}

void Dealer::ShowShuffledCards() {
    for (int i = 0; i < 52; i++) {
        cards[idx[i]].ShowCard();

        // 一组最后一张
        if (i % 13 == 12) {
            cout << "\n";
        }
    }
}

void Dealer::Deal4Cards(Player* player) {
    for (int i = 0; i < 4; i++) {
        player->GetCard(cards[idx[top++]]);
        GetCard(cards[idx[top++]]);
    }
}

int ShowMenu() {
    cout << "1 显示原始的牌\n";
    cout << "2 显示洗牌后的牌\n";
    cout << "3 洗牌\n";
    cout << "4 发牌和ShowHand\n";
    cout << "5 退出\n";
    cout << "请选择: ";

    char buf[6];
    cin.getline(buf, 6);
    return atoi(buf);
}
